#include "network.h"
SongUrlProcess::SongUrlProcess(QNetworkAccessManager *manager, QUrl baseUrl):
    manager(manager), baseUrl(baseUrl)
{

}

void SongUrlProcess::sendRequest(Song song)
{
    m_song = song;
    auto url = baseUrl;
    url.setPath("/song/url");
    QUrlQuery query;
    query.addQueryItem("id", QString::number(song.id));
    url.setQuery(query);
    QNetworkRequest req;
    req.setUrl(url);
    getSongUrlReply = manager->get(req);
    conn();

}

void SongUrlProcess::conn()
{
    connect(getSongUrlReply, &QNetworkReply::readChannelFinished, this, &SongUrlProcess::getSongUrlSlot);

}

Network::Network(const QUrl &baseUrl) :
    baseUrl(baseUrl), songUrlProcess(&this->manager, baseUrl)
{

}

void Network::login(QString user, QString password)
{
    auto url = baseUrl;
    url.setPath("/login/cellphone");
    QUrlQuery query;
    query.addQueryItem("phone", user);
    query.addQueryItem("password", password);
    url.setQuery(query);
    QNetworkRequest req;
    req.setUrl(url);
    loginReply = manager.get(req);
    connect(loginReply, &QNetworkReply::readChannelFinished, this, &Network::loginReplySlot);

}

void Network::loginReplySlot() {
    auto res = loginReply->readAll();
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
    int code = jdoc.object().value("code").toInt();
    if (code != 200) {
        emit loginResult(false);
        qDebug() <<"login failed";
        return ;
    }
    // qDebug() << jdoc.toJson();
    auto account = jdoc.object().value("account").toObject();
    userId = (unsigned)account.value("id").toDouble();
    nickname = jdoc.object().value("profile").toObject().value("nickname").toString();
    cookie = jdoc.object().value("cookie").toString();
    // qDebug() << "login success";
    // qDebug() << userId;
    // qDebug() << nickname;
    // qDebug() << cookie;
    emit loginResult(true);

}

void Network::search(QString keywords, int limit, int offset)
{
    QUrl url = baseUrl;
    url.setPath("/search");
    QUrlQuery query;
    query.addQueryItem("keywords", keywords);
    query.addQueryItem("limit", QString::number(limit));
    query.addQueryItem("offset", QString::number(offset));
    QNetworkRequest req;
    url.setQuery(query);
    req.setUrl(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    // searchReply = manager.post(req, QByteArray().append(query.toString()));
    searchReply = manager.get(req);
    connect(searchReply, &QNetworkReply::readChannelFinished, this, &Network::searchreadyReadSlot);
    // connect(&manager, &QNetworkAccessManager::finished, this, &Network::searchreadyReadSlot);


}


void Network::getSongUrl(Song song)
{
    songUrlProcess.sendRequest(song);
}

void Network::getLyric(unsigned id)
{
    QUrl url = baseUrl;
    url.setPath("/lyric");
    QUrlQuery query;
    query.addQueryItem("id", QString::number(id));
    QNetworkRequest req;
    url.setQuery(query);
    req.setUrl(url);
    getLyricReply = manager.get(req);
    connect(getLyricReply, &QNetworkReply::readChannelFinished, this, &Network::getLyricReadyReadSlot);
}

void Network::getPlayList()
{
    QUrl url = baseUrl;
    url.setPath("/user/playlist");
    QUrlQuery query;
    query.addQueryItem("uid", QString::number(userId));
    QNetworkRequest req;
    url.setQuery(query);
    req.setUrl(url);
    QUrlQuery cookieQuery;
    cookieQuery.addQueryItem("cookie", cookie);
    req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    playListReply = manager.post(req, QByteArray().append(cookieQuery.toString()));
    connect(playListReply, &QNetworkReply::readChannelFinished, this, &Network::playListReadyReadSlot);

}

void Network::getPlayListById(unsigned id)
{
    QUrl url = baseUrl;
    url.setPath("/playlist/detail");
    QUrlQuery query;
    query.addQueryItem("id", QString::number(id));
    QNetworkRequest req;
    url.setQuery(query);
    req.setUrl(url);
    QUrlQuery cookieQuery;
    cookieQuery.addQueryItem("cookie", cookie);
    req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    playListByIdReply = manager.post(req, QByteArray().append(cookieQuery.toString()));
    connect(playListByIdReply, &QNetworkReply::readChannelFinished, this, &Network::playListByIdReadyReadSlot);
}

void Network::logout()
{
    QUrl url = baseUrl;
    url.setPath("/logout");
    QNetworkRequest req;
    req.setUrl(url);
    QUrlQuery cookieQuery;
    cookieQuery.addQueryItem("cookie", cookie);
    req.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
    logoutReply = manager.post(req, QByteArray().append(cookieQuery.toString()));
    connect(logoutReply, &QNetworkReply::readChannelFinished, this, &Network::logoutReadyReadSlot);

}
void Network::logoutReadyReadSlot() {
    auto reply = logoutReply;
    auto res = reply->readAll();
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
    int code = jdoc.object().value("code").toInt();
    if (code != 200) {
        emit logoutSignal(false);
        // qDebug() <<"logout failed";
        return ;
    } else {
        // qDebug() <<"logout seccess";
        emit logoutSignal(true);
    }


}

void Network::getLyricReadyReadSlot() {
    auto reply = getLyricReply;
    auto res = reply->readAll();
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
    QString lyric = jdoc.object().value("lrc").toObject().value("lyric").toString();
    emit getLyricDone(lyric);


}

void Network::playListReadyReadSlot()
{
    auto res = playListReply->readAll();
  //  qDebug() << res;
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
   // qDebug() << jdoc.toJson();
    QList<NetPlayList> playlist;
    QJsonArray array = jdoc.object().value("playlist").toArray();
    for (int i = 0; i < array.size(); i++) {
        auto ob = array[i].toObject();
        playlist.append(NetPlayList{ob.value("name").toString(), (unsigned)ob.value("id").toDouble()});
        // qDebug() << ob.value("name").toString() << " id:" <<(unsigned)ob.value("id").toDouble() << " json:" << ob.value("id");
    }
    emit getPlayListDone(playlist);
   // qDebug() << "getplaylist done!";
}

void Network::playListByIdReadyReadSlot()
{
    auto res = playListByIdReply->readAll();
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
    SongList sl;
    auto ar = jdoc.object().value("playlist").toObject().value("tracks").toArray();
    for (int i = 0; i < ar.size(); i++) {
        QString title;
        QString artist;
        unsigned songId;
        auto item = ar[i].toObject();
        title = item.value("name").toString();
        artist = item.value("ar").toArray()[0].toObject().value("name").toString();
        songId = (unsigned)item.value("id").toDouble();
        sl.append(Song(title, artist, QUrl(), songId));
        //qDebug() << title << " " << artist << " " << songId;
    }
    emit getPlayListByIdDone(sl);



}



void SongUrlProcess::getSongUrlSlot() {
    auto res = getSongUrlReply->readAll();
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }
    QString url = jdoc.object().value("data").toArray()[0].toObject().value("url").toString();
    //qDebug() << url;
    m_song.url = url;
    emit getSongUrlDone(m_song);
    getSongUrlReply->deleteLater();


}

void Network::processSearch(QNetworkReply *reply)
{
    SongList slist;
    auto res = reply->readAll();
    // qDebug() << res;
    QJsonParseError err;
    auto jdoc = QJsonDocument::fromJson(res, &err);
    if (err.error != QJsonParseError::NoError) {
        qDebug() << err.errorString() << endl;
        return ;
    }


    QJsonArray songs = jdoc.object().value("result").toObject().value("songs").toArray();
    for (int i = 0; i < songs.size(); i++) {
        QJsonObject v = songs[i].toObject();
        unsigned int id = (unsigned)v.value("id").toDouble();
        QString songName = v.value("name").toString();
        QString artist = v.value("artists").toArray()[0].toObject().value("name").toString();
        //qDebug() << id << songName.toUtf8() << artist << endl;
        slist.append(Song(songName,artist, QUrl(), id));

    }
    emit searchDone(slist);

   // reply->deleteLater();

}

void Network::searchreadyReadSlot()
{
    this->processSearch(searchReply);
}
